#include "config.h"
#include <stdio.h>

#include "config.h"
#include "init.h"
#include "regs.h"
#include "syscfg.h"
#include "arch.h"
#include "iodev.h"
#include "kernel.h"

#if 0
#define C0_REG_DBG(name)	printf("c0 "#name": 0x%08x\n", read_c0_##name())
void cp0_show_info(void)
{
	C0_REG_DBG(index);
	C0_REG_DBG(random);
	C0_REG_DBG(entrylo0);
	C0_REG_DBG(entrylo1);
	C0_REG_DBG(context);
	C0_REG_DBG(userlocal);
	C0_REG_DBG(pagemask);
	C0_REG_DBG(pagegrain);
	C0_REG_DBG(wired);
	C0_REG_DBG(hwrena);
	C0_REG_DBG(badvaddr);
	C0_REG_DBG(count);
	C0_REG_DBG(entryhi);
	C0_REG_DBG(compare);
	C0_REG_DBG(status);
	C0_REG_DBG(intctl);
	C0_REG_DBG(srsctl);
	C0_REG_DBG(srsmap);
	C0_REG_DBG(viewipl);
	C0_REG_DBG(srsmap2);
	C0_REG_DBG(cause);
	C0_REG_DBG(viewripl);
	C0_REG_DBG(epc);
	C0_REG_DBG(prid);
	C0_REG_DBG(ebase);
	C0_REG_DBG(cdmmbase);
	C0_REG_DBG(config);
	C0_REG_DBG(config1);
	C0_REG_DBG(config2);
	C0_REG_DBG(config3);
	C0_REG_DBG(config7);
	C0_REG_DBG(lladdr);
	C0_REG_DBG(watchlo0);
	C0_REG_DBG(watchlo1);
	C0_REG_DBG(watchlo2);
	C0_REG_DBG(watchlo3);
	C0_REG_DBG(watchlo4);
	C0_REG_DBG(watchlo5);
	C0_REG_DBG(watchlo6);
	C0_REG_DBG(watchlo7);
	C0_REG_DBG(watchhi0);
	C0_REG_DBG(watchhi1);
	C0_REG_DBG(watchhi2);
	C0_REG_DBG(watchhi3);
	C0_REG_DBG(watchhi4);
	C0_REG_DBG(watchhi5);
	C0_REG_DBG(watchhi6);
	C0_REG_DBG(watchhi7);
	C0_REG_DBG(debug);
	C0_REG_DBG(tracectrl1);
	C0_REG_DBG(tracectrl2);
	C0_REG_DBG(usertrcdt1);
	C0_REG_DBG(usertrcdt2);
	C0_REG_DBG(tracebpc);
	C0_REG_DBG(debug2);
	C0_REG_DBG(depc);
	C0_REG_DBG(perfctrl0);
	C0_REG_DBG(perfcntr0);
	C0_REG_DBG(perfctrl1);
	C0_REG_DBG(perfcntr1);
	C0_REG_DBG(errctl);
	C0_REG_DBG(cacheerr);
	C0_REG_DBG(taglo);
	C0_REG_DBG(dtaglo);
	C0_REG_DBG(errorepc);
	C0_REG_DBG(desave);
}
#endif
typedef struct {
	volatile uint32_t pll_cfg;
	volatile uint32_t clk_swt;
	volatile uint32_t clk_gate[2];
	volatile uint32_t clk_div[6];
}syscfg_t;

syscfg_t g_syscfg;

static inline void pll_off(void)
{
    g_syscfg.pll_cfg = SYSCFG->PLL_CFG;
    g_syscfg.clk_swt = SYSCFG->CLK_SWT;

    if (SYSCFG->CLK_SWT | AHB_CLK_PLL) {
        SYSCFG->CLK_SWT &= ~AHB_CLK_PLL;
    }
    SYSCFG->PLL_CFG = MOSC_EN;
    SYSCFG->CLK_SWT |= 0x5e;   

}

static inline void pll_on(void)
{
	SYSCFG->PLL_CFG = g_syscfg.pll_cfg;
	SYSCFG->CLK_SWT = (g_syscfg.clk_swt);
}
void clk_gate_off(void)
{
	g_syscfg.clk_gate[0] = SYSCFG->CLK_GATE0;
	g_syscfg.clk_gate[1] = SYSCFG->CLK_GATE1;

	g_syscfg.clk_div[0] = SYSCFG->CLK_DIV0;
	g_syscfg.clk_div[1] = SYSCFG->CLK_DIV1;
	g_syscfg.clk_div[2] = SYSCFG->CLK_DIV2;
	g_syscfg.clk_div[3] = SYSCFG->CLK_DIV3;
	g_syscfg.clk_div[4] = SYSCFG->CLK_DIV4;
	g_syscfg.clk_div[5] = SYSCFG->CLK_DIV5;	
	
	SYSCFG->CLK_GATE0  =  EFLASH_CLK_EN | GPIO_CLK_EN | SRAM_CLK_EN |\
				PCLK0_EN | DEF_CLK_EN | RTC_CLK_EN | PCLK1_CLK_EN | ICTL_CLK_EN | EMI_CLK_EN;

	SYSCFG->CLK_GATE1 = DEF_CLK2_EN;
    
	SYSCFG->CLK_DIV0 = FSK_DIV(0x4000) | PCLK1_DIV(1) | PCLK0_DIV(1) | HCLK_DIV(1);
	SYSCFG->CLK_DIV1 = 0xffffffff;
	SYSCFG->CLK_DIV2 = 0xffffffff;
	SYSCFG->CLK_DIV3 = 0xffffffff & ~(DEF_DIV_MSK);
	SYSCFG->CLK_DIV4 = 0xffffffff;
	SYSCFG->CLK_DIV5 = 0xffffffff;

}

void clk_gate_on(void)
{

	SYSCFG->CLK_GATE0 = g_syscfg.clk_gate[0];
	SYSCFG->CLK_GATE1 = g_syscfg.clk_gate[1];

	SYSCFG->CLK_DIV0 = g_syscfg.clk_div[0];
	SYSCFG->CLK_DIV1 = g_syscfg.clk_div[1];
	SYSCFG->CLK_DIV2 = g_syscfg.clk_div[2];
	SYSCFG->CLK_DIV3 = g_syscfg.clk_div[3];
	SYSCFG->CLK_DIV4 = g_syscfg.clk_div[4];
	SYSCFG->CLK_DIV5 = g_syscfg.clk_div[5];
	
	
}

void arch_suspend(void)
{
	__disable_interrupt();
	pll_off();
	clk_gate_off();
	__enable_interrupt();
}

void arch_resume(void)
{
	__disable_interrupt();
	clk_gate_on();
	pll_on();
	__enable_interrupt();
}


